home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / tools / netzwerk / parnet / sources / parnet.c < prev    next >
C/C++ Source or Header  |  1996-02-26  |  8KB  |  398 lines

  1.  
  2. /*
  3.  *  PARNET.C
  4.  *
  5.  */
  6.  
  7. #include "defs.h"
  8. #include <resources/misc.h>
  9. #include <hardware/cia.h>
  10. #include <exec/memory.h>
  11.  
  12. extern func_ptr DeviceVectors[];
  13. extern void (*UnitVectors[])(Iob *, long, long);
  14. extern char DeviceName[];
  15. extern char IdString[];
  16.  
  17. extern void VInt(void);                         /*  wakeup.asm  */
  18. extern Task *VTask;                /*  wakeup.asm    */
  19. extern long VMask;                /*  wakeup.asm    */
  20. extern __stdargs int AutoAllocMiscResource(int, int);     /*  wakeup.asm  */
  21. extern __stdargs int AutoFreeMiscResource(int);           /*  wakeup.asm  */
  22. extern __stdargs int VAddICRVector(int, int, struct Interrupt *); /*  wakeup.asm  */
  23. extern __stdargs int VRemICRVector(int, int, struct Interrupt *); /*  wakeup.asm  */
  24.  
  25. long    SysBase    = NULL;    /*  sysbase            */
  26. Device    *DevBase   = NULL;    /*  device base         */
  27. BPTR    DevSegment = NULL;    /*  seglist for device        */
  28. long    PLock[2]   = { 0, 0 };    /*  arbitrate network access    */
  29. PubPort *StickyPort= NULL;
  30.  
  31. char    ActiveMRPP = 0;
  32. char    ActiveMRPB = 0;
  33. char    ActiveTask = 0;
  34. char    ActiveInt  = 0;
  35.  
  36. struct Interrupt VInterrupt = {
  37.     {
  38.     NULL, NULL,
  39.     NT_INTERRUPT,
  40.     -126,
  41.     "parnet.device"
  42.     },
  43.     NULL,
  44.     VInt
  45. };
  46.  
  47. /* Prototyping */
  48.  
  49. APTR CDevInit(BPTR);
  50. Device *CDevOpen(long,long,Iob *);
  51. long CDevExpunge(void);
  52. BPTR CDevClose(Iob *);
  53. void ReadConfig(void);
  54. void WriteConfig(void);
  55. int DetermineTimeouts(void);
  56.  
  57. /*
  58.  *  Init is called when the device is loaded to create it.
  59.  */
  60.  
  61. APTR
  62. CDevInit(seg)
  63. BPTR seg;
  64. {
  65.     Device *db;
  66.  
  67.     SysBase = *(long *)4;
  68.  
  69.     DevBase = db = (Device *)MakeLibrary((long **)DeviceVectors,NULL,NULL,sizeof(Device),NULL);
  70.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  71.     db->Lib.lib_Node.ln_Name = DeviceName;
  72.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  73.     db->Lib.lib_Version = 1;
  74.     db->Lib.lib_IdString= (APTR)IdString;
  75.     db->ParAddress = 254;            /*    default address     */
  76.     db->Port.mp_Node.ln_Type = NT_MSGPORT;
  77.     db->Port.mp_SigBit = SIGBREAKB_CTRL_E;  /*    for VTask        */
  78.     db->Port.mp_Flags  = PA_SIGNAL;
  79.     NewList(&db->UnitList);
  80.     NewList(&db->Port.mp_MsgList);
  81.  
  82.     ReadConfig();
  83.     WriteConfig();
  84.  
  85.     DevSegment = seg;
  86.     AddDevice((struct Device *)db);
  87.     return((APTR)db);
  88. }
  89.  
  90. Device *
  91. CDevOpen(unitnum, flags, iob)
  92. long unitnum;
  93. long flags;
  94. Iob *iob;
  95. {
  96.     Device *nd = DevBase;
  97.  
  98.     iob->io_Unit = NULL;
  99.  
  100.     LockAddr(PLock);        /*  because we make calls that kill Forbid()    */
  101.  
  102.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  103.  
  104.     if (++nd->Lib.lib_OpenCnt == 1) {
  105.     /*
  106.      *  Initial Open, allocate resources
  107.      */
  108.  
  109.     if (AutoAllocMiscResource(MR_PARALLELPORT, -1)) {
  110.         iob->io_Actual = PPERR_NOPORTRES;
  111.         goto badop;
  112.     }
  113.     ActiveMRPP = 1;
  114.     if (AutoAllocMiscResource(MR_PARALLELBITS, -1)) {
  115.         iob->io_Actual = PPERR_NOBITSRES;
  116.         goto badop;
  117.     }
  118.     ActiveMRPB = 1;
  119.     VTask = CreateTask("parnet.device", 0, (APTR)ParNetTask, 4096);
  120.     if (VTask == NULL) {
  121.         iob->io_Actual = PPERR_NOTASK;
  122.         goto badop;
  123.     }
  124.     ActiveTask = 1;
  125.     VMask = SIGBREAKF_CTRL_F;
  126.     nd->Port.mp_SigTask = VTask;    /*  for asynchronous I/O    */
  127.  
  128.     if (VAddICRVector(0, CIAICRB_FLG, &VInterrupt)) {
  129.         iob->io_Actual = PPERR_NOINT;
  130.         goto badop;
  131.     }
  132.     ActiveInt = 1;
  133.  
  134.     if (DetermineTimeouts() < 0)    /*  couldn't use timer.device   */
  135.         goto badop;
  136.  
  137.     }
  138.     iob->io_Actual= 0;
  139.     iob->io_Error = 0;
  140.  
  141.     /*
  142.      *    Attempt to open the specified unit by protocol
  143.      */
  144.  
  145.     {
  146.     short proto = iob->io_Flags & PRO_MASK;
  147.  
  148.     if (proto <= PRO_LAST) {
  149.         (*UnitVectors[proto])(iob, unitnum, flags);
  150.         if (iob->io_Error == 0) {
  151.         UnlockAddr(PLock);
  152.         return(nd);
  153.         }
  154.     }
  155.     }
  156.  
  157.     /*
  158.      *    OPEN FAILED
  159.      */
  160.  
  161. badop:
  162.     CDevClose(iob);
  163.     iob->io_Actual = iob->io_Error;
  164.     iob->io_Error  = IOERR_OPENFAIL;
  165.     UnlockAddr(PLock);
  166.     return(NULL);
  167. }
  168.  
  169. long
  170. CDevExpunge(void)
  171. {
  172.     Device *nd = DevBase;
  173.     BPTR ds = DevSegment;
  174.  
  175.     if (ds == NULL)
  176.     Alert(24);
  177.  
  178.     if (nd->Lib.lib_OpenCnt) {              /*  delayed expunge */
  179.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  180.     return(NULL);
  181.     }
  182.     Remove((NODE *)nd);
  183.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  184.     DevSegment = NULL;
  185.     return(ds);
  186. }
  187.  
  188. BPTR
  189. CDevClose(iob)
  190. Iob *iob;
  191. {
  192.     Device *nd = DevBase;
  193.  
  194.     if (iob->io_Unit)
  195.     (*iob->io_Unit->CloseFunc)(iob);
  196.  
  197.     iob->io_Unit   = NULL;            /*  clear vectors    */
  198.     iob->io_Device = NULL;
  199.  
  200.     if (nd->Lib.lib_OpenCnt == 1)   {           /*  last close          */
  201.     if (ActiveInt)
  202.         VRemICRVector(0, CIAICRB_FLG, &VInterrupt);
  203.     if (ActiveTask)
  204.         RemTask(VTask);
  205.     if (ActiveMRPB)
  206.         AutoFreeMiscResource(MR_PARALLELBITS);
  207.     if (ActiveMRPP)
  208.         AutoFreeMiscResource(MR_PARALLELPORT);
  209.     ActiveInt = 0;
  210.     ActiveTask= 0;
  211.     ActiveMRPB= 0;
  212.     ActiveMRPP= 0;
  213.     }
  214.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  215.     return(NULL);                           /*  still has refs      */
  216.  
  217.     /*
  218.      *    Note: LIBF_DELEXP never set if DevClose() called from DevOpen()
  219.      */
  220.  
  221.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  222.     return(CDevExpunge());                  /*  expunge             */
  223.     return(NULL);                               /*  no expunge          */
  224. }
  225.  
  226. /*
  227.  *  UNITS
  228.  */
  229.  
  230. Unit *UnitCache = NULL;
  231.  
  232. Unit *
  233. FindUnitForPort(port)
  234. uword port;
  235. {
  236.     Unit *unit;
  237.     Device *db;
  238.  
  239.     if (UnitCache && port == UnitCache->Port)
  240.     return(UnitCache);
  241.  
  242.     db = DevBase;
  243.     for (unit = (Unit *)db->UnitList.lh_Head; unit != (Unit *)&db->UnitList.lh_Tail; unit = (Unit *)unit->Node.ln_Succ) {
  244.     if (port == unit->Port) {
  245.         UnitCache = unit;
  246.         return(unit);
  247.     }
  248.     }
  249.     return(NULL);
  250. }
  251.  
  252. Unit *
  253. AllocUnit(iob, beginFunc, abortFunc, dataFunc, closeFunc)
  254. Iob *iob;
  255. func_void beginFunc;
  256. func_void abortFunc;
  257. func_void dataFunc;
  258. func_void closeFunc;
  259. {
  260.     Unit *unit = AllocMem(sizeof(Unit), MEMF_CLEAR | MEMF_PUBLIC);
  261.     Device *db = DevBase;
  262.  
  263.     unit->BeginIO = beginFunc;
  264.     unit->AbortIO = abortFunc;
  265.     unit->CloseFunc = closeFunc;
  266.     unit->DataFunc = dataFunc;
  267.  
  268.     unit->Port = iob->io_Port;
  269.     unit->Protocol = iob->io_Flags & PRO_MASK;
  270.     unit->DestAddr = iob->io_Addr;
  271.  
  272.     NewList(&unit->PendIOR);
  273.     NewList(&unit->PendIOW);
  274.     NewList(&unit->PendCon);
  275.     NewList(&unit->PendLsn);
  276.  
  277.     AddHead(&db->UnitList, (struct Node *)unit);
  278.  
  279.     return(unit);
  280. }
  281.  
  282. void
  283. FreeUnit(unit)
  284. Unit *unit;
  285. {
  286.     Remove(&unit->Node);
  287.     FreeMem(unit, sizeof(Unit));
  288.     UnitCache = NULL;
  289. }
  290.  
  291. /*
  292.  *  Packets
  293.  */
  294.  
  295. Packet *
  296. AllocParPacket(iob, unit, data1, bytes1, data2, bytes2)
  297. Iob *iob;
  298. Unit *unit;
  299. ubyte *data1;
  300. ubyte *data2;
  301. long bytes1;
  302. long bytes2;
  303. {
  304.     Packet *packet = AllocMem(sizeof(Packet), MEMF_CLEAR|MEMF_PUBLIC);
  305.  
  306.     packet->iob = iob;
  307.     packet->io_Unit = unit;
  308.     if (iob)
  309.     packet->DestAddr = iob->io_Addr;
  310.     packet->DestPort = unit->Port;
  311.     packet->Data1 = data1;
  312.     packet->Data2 = data2;
  313.     packet->DLen1 = bytes1;
  314.     packet->DLen2 = bytes2;
  315.  
  316.     return(packet);
  317. }
  318.  
  319. void
  320. FreeParPacket(packet)
  321. Packet *packet;
  322. {
  323.     FreeMem(packet, sizeof(Packet));
  324. }
  325.  
  326. /*
  327.  *                CONFIG
  328.  */
  329.  
  330. void
  331. ReadConfig(void)
  332. {
  333.     PubPort *port;
  334.  
  335.     if ((port = StickyPort) == NULL)
  336.     port = (PubPort *)FindPort(PORTNAME);
  337.  
  338.     if (port) {
  339.     DevBase->ParAddress = port->Address;
  340.     ParAddress(DevBase->ParAddress);
  341.     /*ParLLTimeout = port->Timeout;*/
  342.     }
  343.     StickyPort = port;
  344. }
  345.  
  346. void
  347. WriteConfig(void)
  348. {
  349.     char *portName = PORTNAME;
  350.     PubPort *port;
  351.  
  352.     if ((port = StickyPort) == NULL && (port = (PubPort *)FindPort(portName)) == NULL) {
  353.     port = AllocMem(sizeof(PubPort) + strlen(portName) + 1, MEMF_PUBLIC | MEMF_CLEAR);
  354.     port->Port.mp_Node.ln_Name = (char *)(port + 1);
  355.  
  356.     strcpy(port->Port.mp_Node.ln_Name, portName);
  357.     port->Port.mp_Node.ln_Type = NT_MSGPORT;
  358.     port->Port.mp_Node.ln_Pri  = 0;
  359.     NewList(&port->Port.mp_MsgList);
  360.     AddPort((PORT *)port);
  361.     }
  362.     port->Address = DevBase->ParAddress;
  363.     port->Timeout = ParLLTimeout;
  364.     StickyPort = port;
  365. }
  366.  
  367. /*
  368.  *  Determines the processor speed for soft wired timeouts in PAR.ASM
  369.  *  by timing 1 second.
  370.  */
  371. int
  372. DetermineTimeouts(void)
  373. {
  374.     IOT iot;
  375.     long cnt = 0;
  376.     PORT *port = CreatePort(NULL, 0);
  377.  
  378.     if (OpenDevice(TIMERNAME, UNIT_VBLANK, &iot, 0))
  379.     return(-1);
  380.     iot.tr_node.io_Command = TR_ADDREQUEST;
  381.     iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  382.     iot.tr_node.io_Message.mn_ReplyPort = port;
  383.     iot.tr_time.tv_secs = 1;
  384.     iot.tr_time.tv_micro= 0;
  385.     SendIO(&iot);
  386.     while (CheckIO(&iot) == NULL) {
  387.     Time10000();
  388.     cnt += 10000;
  389.     }
  390.     WaitIO(&iot);
  391.     ParLLTimeout = cnt;
  392.     CloseDevice(&iot);
  393.     DeletePort(port);
  394.     return(0);
  395. }
  396.  
  397.  
  398.